#include "TcpServer.h"

#ifdef _WIN32

TcpClient TcpServer::Accept()
{

    TcpClient res;
    int len = sizeof(sockaddr_in);
    res.sock = accept(sock, (sockaddr*)&res.clientAddr, &len);

    return res;

}

bool TcpServer::Create(const TcpServer::Desc& desc)
{

    WSADATA wsadata;
    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        LOGI("Failed init wsaData");
        return 0;
    }
    LOGI("WSA Startup");

    if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wVersion) != 2) {

        LOGI("Could not find a usable version of Winsock.dll");
        WSACleanup();
        return 0;
    }

    sock = socket(desc.af, desc.type, desc.protocol);
    if (INVALID_SOCKET == sock)
    {
        LOGI("InValid socket");
        return 0;
    }

    struct sockaddr_in addr;
    addr.sin_addr.S_un.S_addr = desc.sAddr;
    addr.sin_family = desc.sinFamily;
    addr.sin_port = htons(desc.port);

    if (SOCKET_ERROR == bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)))
    {
        LOGI("Socket error");
        return 0;
    }

    LOGI("success bind port %d", desc.port);

    if (SOCKET_ERROR == listen(sock, desc.backLog))
    {
        LOGI("Socket error");
        return 0;

    }
    LOGI("tcp server listen on port:%d", desc.port);

    return 1;
}

void TcpServer::Close()
{
    closesocket(sock);
    WSACleanup();
}


#endif // _WIN32


#ifdef __linux__
TcpClient TcpServer::Accept()
{
    TcpClient res;
    static socklen_t len = sizeof(sockaddr_in);
    res.sock = accept(sock, (sockaddr *)&res.clientAddr, &len);
    return res;
}

bool TcpServer::Create(const Desc &desc)
{
    struct sockaddr_in servaddr, cliaddr; // ??????????????
    socklen_t cliaddr_len;                // ???????
    sock = socket(desc.af, desc.type, desc.protocol);
    if (sock == -1)
    {
        LOGI("socket failed return %d", socket);
        return false;
    }
    // memset(&servaddr, 0, sizeof(servaddr)); // ??????????
    servaddr.sin_family = desc.af;
    servaddr.sin_addr.s_addr = htonl(desc.sAddr);
    servaddr.sin_port = htons(desc.port);
    int bind_res = bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr));

    // LOGI("bind res %d", bind_res);
    if (bind_res != 0)
    {
        LOGI("cannot bind %d", desc.sAddr, desc.port);
        return false;
    }
    LOGI("success bind port %d", desc.port);

    int listen_res = listen(sock, desc.backLog);
    if (listen_res != 0)
    {
        LOGI("cannot listen %d", desc.sAddr, desc.port);
        return false;
    }

    LOGI("tcp server listen on port:%d", desc.port);

    return true;
}

void TcpServer::Close()
{
    close(this->sock);
}
#endif
